// © 2009 Microsoft Corporation.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Activation;
using System.Security.Permissions;
using System.Threading;

using Microsoft.InformationSecurity.ISRM.TaskManagment.Classes;
using Microsoft.InformationSecurity.CISF.Security;

namespace Microsoft.InformationSecurity.ISRM.TaskManagment.WebService
{
    /// <summary>
    /// Implementation of the notifications WCF interface.
    /// </summary>
    public class NotificationsService : INotificationsService
    {
        const string eventSource = "Risk Tracker";
        const string logName = "Risk Service"; 

        #region INotificationsService Members
        /// <summary>
        /// Adds notification content to the database.
        /// </summary>
        /// <param name="notificationContent">New notification content</param>
        /// <returns>Notification Content ID</returns>
        public int AddNotificationContent(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationContent notificationContent)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                return Notifications.AddNotificationContent(notificationContent);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        /// <summary>
        /// Updates notification content in the database.
        /// </summary>
        /// <param name="notificationContent">Updated Notification Content</param>
        public void UpdateNotificationContent(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationContent notificationContent)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Notifications.UpdateNotificationContent(notificationContent);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        /// <summary>
        /// Deletes an existing notification content from the database.
        /// </summary>
        /// <param name="notificationContentID">Notification Content ID</param>
        /// <param name="personID">PersonID of the user doing the action</param>
        public void DeleteNotificationContent(int notificationContentID, int personID)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Notifications.DeleteNotificationContent(notificationContentID, personID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }         
        }

        /// <summary>
        /// Returns list of all notification contents
        /// </summary>
        /// <returns>List of Notification Contents</returns>
        public List<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationContent> GetNotificationContents()
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                return Notifications.GetNotificationContents();
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }                    
        }

        /// <summary>
        /// Adds a new notification schedule to the database.
        /// </summary>
        /// <param name="notificationSchedule">New Notificaiton Schedule</param>
        /// <returns>Notification Schedule ID</returns>
        public int AddNotificationSchedule(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationSchedule notificationSchedule)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                return Notifications.AddNotificationSchedule(notificationSchedule);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }  
        }

        /// <summary>
        /// Updates notification schedule in the database.
        /// </summary>
        /// <param name="notificationSchedule">Updated notification schedule</param>
        public void UpdateNotificationSchedule(Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationSchedule notificationSchedule)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Notifications.UpdateNotificationSchedule(notificationSchedule);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }  
        }

        /// <summary>
        /// Deletes an existing notification schedule from the database.
        /// </summary>
        /// <param name="notificationScheduleID">Notification Schedule ID</param>
        /// <param name="personID">PersonID of the user doing the action</param>
        public void DeleteNotificationSchedule(int notificationScheduleID, int personID)
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Notifications.DeleteNotificationSchedule(notificationScheduleID, personID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }        
        }
        
        /// <summary>
        /// Returns the list of all notification schedules from the database.
        /// </summary>
        /// <returns>List of Notification Schedules</returns>
        public List<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationSchedule> GetNotificationSchedules()
        {
            
            List<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationSchedule> notificationSch = null;
            try
            {
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;

                if (principal.IsInRole("Task User") || principal.IsInRole("Risk User") || principal.IsInRole("Task Admin"))
                    notificationSch = (List<Microsoft.InformationSecurity.ISRM.TaskManagment.Classes.NotificationSchedule>)Notifications.GetNotificationSchedules();
                else
                    throw new System.Security.SecurityException("Permission denied.");

                return notificationSch;
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }        
        }

        /// <summary>
        /// Returns notification schedule details.
        /// </summary>
        /// <param name="scheduleID">Notification Schedule Identifier</param>
        /// <returns>Notification Schedule Details</returns>
        public NotificationSchedule GetNotificationSchedule(int scheduleID) 
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                return Notifications.GetNotificationSchedule(scheduleID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        /// <summary>
        /// Sets the default notification schedule in the database.
        /// </summary>
        /// <param name="notificationScheduleID">Notification Schedule Identifier</param>
        /// <param name="username">Username</param>
        /// <param name="personID">PersonID of the user doing the action</param>
        public void SetDefaultNotificationSchedule(int notificationScheduleID,string username, int personID) 
        {            
            try
            {
                PrincipalPermission permission = new PrincipalPermission(ServiceSecurityContext.Current.WindowsIdentity.Name, "Task Admin", true);
                permission.Demand();

                Notifications.SetDefaultNotificationSchedule(notificationScheduleID, username, personID);
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }
        }

        /// <summary>
        /// Returns the default notification schedule from the database.
        /// </summary>
        /// <returns>Notification Schedule Identifier</returns>
        public int GetDefaultNotificationSchedule()
        {            
            int ret;
            try
            {
                Microsoft.InformationSecurity.CISF.Security.Principal.CISFPrincipal principal = (CISF.Security.Principal.CISFPrincipal)Thread.CurrentPrincipal;
                ret = -1;
                if (principal.IsInRole("Task User") || principal.IsInRole("Risk User"))
                    ret = Notifications.GetDefaultNotificationSchedule();
                else
                    throw new System.Security.SecurityException("Permission denied.");

                return ret;
            }
            catch (System.Security.SecurityException secExcption)
            {
                // Log Error
                if (!EventLog.SourceExists(eventSource))
                    EventLog.CreateEventSource(logName, logName);
                EventLog.WriteEntry(eventSource, secExcption.Message + "\n" + "Stack:" + secExcption.StackTrace, EventLogEntryType.FailureAudit, 1000);

                throw secExcption; // Do not swollow it, let the expeception propagate.
            }            
        }

        #endregion
    }
}
